package com.chuan.icons;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import com.sonalb.net.http.cookie.Client;
import com.sonalb.net.http.cookie.CookieJar;
import com.sonalb.net.http.cookie.MalformedCookieException;

public class Renren extends SiteBase {
	private static Pattern mFramePattern = Pattern
			.compile(
					"<iframe name=\"iframe_canvas\" id=\"iframe_canvas\" src=\"(.*?)\" frameborder=\"0\"",
					Pattern.MULTILINE);
	private String mPassword = "";

	private final String APP_URL = "http://apps.renren.com/anewrer/";
	private final String LOGIN_URL = "http://passport.renren.com/PLogin.do";
	private final String INSTALL_APP_URL = "http://app.renren.com/apps/tos.do?api_key=84aef246f9114aff95190f45778dd3f6";
	private final String INSTALL_POST = "api_key=84aef246f9114aff95190f45778dd3f6&next=&id=13721&rating=0.1&xn_api_transfer_origin=0.1&needSendFeed=1";

	private Client mLoginClient = null;
	private CookieJar mLoginCookieJar = null;

	Renren(FriendActivity context) {
		super(context);
		mSite = "renren";
	}

	public JSONArray getAccountInfo() {
		JSONArray ary = new JSONArray();
		ary.put("username");
		ary.put("password");
		return ary;
	}

	private Boolean isAppInstall(String iframe_url) {
		if (iframe_url.contains("xn_sig_user")
				&& iframe_url.contains("xn_sig_session_key")) {
			return true;
		}
		return false;
	}

	private Boolean fetchFriendsByApp(String user_url) {
		updateDiagInfo(R.string.str_fetch_account);
		String friendsbuf = new String(SiteBase.httpDownload(user_url));
		if (friendsbuf == null || friendsbuf.length() < 1) {
			updateDiagInfo(R.string.str_fetch_account_fail);
			return false;
		}
		updateDiagInfo(R.string.str_fetch_account_success);
		return parseFriends(friendsbuf);
	}

	@Override
	public Boolean getFriendsList(JSONObject info) {
		try {
			mUser = info.getString(Constants.PARAMETER_USER);
			mPassword = info.getJSONObject(Constants.PARAMETER_PARAMETER)
					.getString("password");
		} catch (JSONException e) {
			return false;
		}

		updateDiagInfo(R.string.str_login);
		String url = getLoginURL();
		if (url == null) {
			updateDiagInfo(R.string.str_login_fail);
			Log.d(Constants.LOG_FLAG, "Login fail.");
			return false;
		}

		if (getLoginedCookies(url)) {
			String user_url = getFrameURL();
			// 此处，已经授权了应用的用户将会得到正确的iframe值，而尚未安装的用户则需要授权。
			if (isAppInstall(user_url)) {
				return fetchFriendsByApp(user_url);
			} else {
				// 尝试获取 App 授权。
				installApp();
				user_url = getFrameURL();
				if (isAppInstall(user_url)) {
					return fetchFriendsByApp(user_url);
				} else {
					return false;
				}
			}
		}

		return false;
	}

	private Boolean parseFriends(String friendsbuf) {
		JSONArray ary;
		try {
			ary = new JSONArray(friendsbuf);
		} catch (JSONException e) {
			return false;
		}

		LiteDB.mDB.beginTransaction();
		try {
			for (int i = 0; i < ary.length(); ++i) {
				try {
					JSONObject obj = ary.getJSONObject(i);
					Log.d(Constants.LOG_FLAG, "Try to add "
							+ obj.getString("name") + " " + obj.getString("id")
							+ " " + obj.getString("tinyurl"));
					addFriends(obj.getString("id"), obj.getString("name"), obj
							.getString("tinyurl"));
				} catch (JSONException e) {
					continue;
				}
			}
			LiteDB.mDB.setTransactionSuccessful();
		} finally {
			LiteDB.mDB.endTransaction();
		}

		return true;
	}

	private String getFrameURL() {
		URL target_url;
		try {
			target_url = new URL(APP_URL);
		} catch (MalformedURLException e1) {
			return null;
		}

		HttpURLConnection conn;
		StringBuffer buffer = new StringBuffer();
		try {
			conn = (HttpURLConnection) target_url.openConnection();
			conn.setInstanceFollowRedirects(false);
			mLoginClient.setCookies(conn, mLoginCookieJar);

			conn.connect();

			BufferedReader br = new BufferedReader(new InputStreamReader(conn
					.getInputStream()));
			String line;

			while ((line = br.readLine()) != null) {
				buffer.append(line);
				buffer.append("\n");
			}

			br.close();
			// Log.e(Constants.LOG_FLAG, buffer.toString());
		} catch (IOException e) {
			Log.e(Constants.LOG_FLAG, "Download fail.", e);
			return null;
		} catch (Exception e) {
			Log.e(Constants.LOG_FLAG, "Download fail.", e);
			return null;
		}

		Matcher match = mFramePattern.matcher(buffer.toString());
		if (match.find()) {
			String iframe = match.group(1).replace("http://faye.appspot.com/",
					"http://faye.appspot.com/getuser");
			Log.e(Constants.LOG_FLAG, "Get iframe: " + iframe);
			return iframe;
		}

		return null;
	}

	private Boolean getLoginedCookies(String url) {
		URL target_url;
		try {
			target_url = new URL(url);
		} catch (MalformedURLException e1) {
			return false;
		}

		HttpURLConnection conn;
		try {
			conn = (HttpURLConnection) target_url.openConnection();
			conn.setInstanceFollowRedirects(false);
			conn.connect();

			mLoginClient = new Client();
			try {
				mLoginCookieJar = mLoginClient.getCookies(conn);
			} catch (MalformedCookieException e) {
				return false;
			}

			conn.disconnect();
			return true;

		} catch (IOException e) {
			return false;
		} catch (Exception e) {
			Log.e(Constants.LOG_FLAG, "Download fail.", e);
			return false;
		}
	}

	private String getLoginURL() {
		URL url;
		try {
			url = new URL(LOGIN_URL);
		} catch (MalformedURLException e) {
			return null;
		}

		HttpURLConnection conn;
		try {
			conn = (HttpURLConnection) url.openConnection();
		} catch (IOException e) {
			return null;
		}

		conn.setDoOutput(true);
		try {
			conn.setConnectTimeout(10000);
			conn.setRequestMethod("POST");
			conn.setInstanceFollowRedirects(false);
			conn.setRequestProperty("Content-Type",
					"application/x-www-form-urlencoded");
		} catch (ProtocolException e) {
			return null;
		}

		String content;
		try {
			content = URLEncoder.encode("email", "UTF-8") + "="
					+ URLEncoder.encode(mUser, "UTF-8");
			content += "&" + URLEncoder.encode("password", "UTF-8") + "="
					+ URLEncoder.encode(mPassword, "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			return null;
		}

		OutputStream http_output = null;

		try {
			http_output = conn.getOutputStream();
			http_output.write(content.getBytes("UTF8"));
			http_output.flush();
			http_output.close();

			conn.connect();

		} catch (IOException e) {
			return null;
		}

		try {
			if (conn.getResponseCode() == 302) {
				String jumpurl = conn.getHeaderField("location");
				conn.disconnect();
				return jumpurl;
			} else if (conn.getResponseCode() == 200) {
				StringBuffer buffer = new StringBuffer();
				BufferedReader br = new BufferedReader(new InputStreamReader(
						conn.getInputStream()));
				String line;

				while ((line = br.readLine()) != null) {
					buffer.append(line);
					buffer.append("\n");
				}

				br.close();
				return null;
			}
		} catch (IOException e) {
			conn.disconnect();
			return null;
		}

		conn.disconnect();
		return null;
	}

	@Override
	public Boolean pairFriends(JSONObject info) {
		LiteDB.mDB.beginTransaction();
		Boolean retval = false;
		try {
			retval = pairFriendsByName(info);
			LiteDB.mDB.setTransactionSuccessful();
		} finally {
			LiteDB.mDB.endTransaction();
		}
		return retval;
	}

	private Boolean installApp() {
		URL target_url;
		try {
			target_url = new URL(INSTALL_APP_URL);
		} catch (MalformedURLException e1) {
			return null;
		}

		HttpURLConnection conn;
		try {
			conn = (HttpURLConnection) target_url.openConnection();

			conn.setDoOutput(true);
			try {
				conn.setConnectTimeout(10000);
				conn.setRequestMethod("POST");
				conn.setRequestProperty("Content-Type",
						"application/x-www-form-urlencoded");

				mLoginClient.setCookies(conn, mLoginCookieJar);
			} catch (ProtocolException e) {
				return false;
			}

			String content;
			try {
				content = URLEncoder.encode("api_key", "UTF-8")
						+ "="
						+ URLEncoder.encode("84aef246f9114aff95190f45778dd3f6",
								"UTF-8");
				content += "&" + URLEncoder.encode("id", "UTF-8") + "="
						+ URLEncoder.encode("13721", "UTF-8");
				content += "&" + URLEncoder.encode("id", "UTF-8") + "="
						+ URLEncoder.encode("13721", "UTF-8");
				content += "&" + URLEncoder.encode("rating", "UTF-8") + "="
						+ URLEncoder.encode("0.1", "UTF-8");
				content += "&"
						+ URLEncoder.encode("xn_api_transfer_origin", "UTF-8")
						+ "=" + URLEncoder.encode("0.1", "UTF-8");
				content += "&" + URLEncoder.encode("needSendFeed", "UTF-8")
						+ "=" + URLEncoder.encode("1", "UTF-8");
			} catch (UnsupportedEncodingException e1) {
				return null;
			}

			OutputStream http_output = null;

			try {
				http_output = conn.getOutputStream();
				http_output.write(content.getBytes("UTF8"));
				http_output.flush();
				http_output.close();

				conn.connect();

			} catch (IOException e) {
				return null;
			}

			conn.connect();

			if (conn.getResponseCode() == 302) {
				// Install okay
				conn.disconnect();
				return true;
			}
		} catch (IOException e) {
			Log.e(Constants.LOG_FLAG, "Download fail.", e);
			return null;
		} catch (Exception e) {
			Log.e(Constants.LOG_FLAG, "Download fail.", e);
			return null;
		}
		conn.disconnect();
		return false;
	}
}
